package traverser;

public class Main {

	public static int trials;
	public static int traverses;

	public static final int CONFIGS = 6;

	public static void printUsage () {
		String usage =
				"Compares Keyword Traverser and Thread Traverser\n" +
				"arg0 = traverses\n" +
				"arg1 = trials per traverse\n";

		System.err.println(usage);
		System.exit(1);
	}

	public static void main(String[] args) {
		KeywordTraverser.quiet = true;
		MasterThread.quiet = true;

		long startTime, endTime;
		long [] time = new long[CONFIGS];
		long [] avgTime = new long[CONFIGS];
		int [] steps = new int[CONFIGS];
		int [] avgSteps = new int[CONFIGS];
		int [] pathLen = new int[CONFIGS];
		int [] avgPathLen = new int[CONFIGS];
		int minPathLen;
		int config;

		try {
			traverses = Integer.parseInt(args[0]);
			trials = Integer.parseInt(args[1]);
		} catch (ArrayIndexOutOfBoundsException e) {
			printUsage();
		} catch (NumberFormatException e) {
			printUsage();
		}

		for (int i = 0; i < traverses; i++) {
			String startPage = FrequencyCollector.getRandomPage();
			String endPage = FrequencyCollector.getRandomPage();
//			String startPage = "http://en.wikipedia.org/wiki/Photograph";
//			String endPage = "http://en.wikipedia.org/wiki/Apple";


			System.out.println("Traverse " + i);
			System.out.println("Start page: " + startPage);
			System.out.println("End   page: " + endPage);

            // Have a traverse go in front, to seed the cache
            MasterThread.new_ranks = true;
            MasterThread.view_threshold = 0;
            MasterThread vanguard = new MasterThread(startPage, endPage);
            vanguard.traverse();
            // allow garbage collection
            vanguard = null;


			minPathLen = 100000;
			for (int c = 0; c < CONFIGS; c++) {
				avgPathLen[c] = 0;
				avgSteps[c] = 0;
				avgTime[c] = 0;
			}

			// Run a BFS, for demo purposes
			config = 5;
            startTime = System.currentTimeMillis();
			TrieTraverser bfs = new TrieTraverser(startPage, endPage);
			steps[config] = bfs.traverse(true);
			avgSteps[config] += steps[config];
			pathLen[config] = bfs.getPathLength();
			avgPathLen[config] += pathLen[config];
			if (minPathLen > pathLen[config] && pathLen[config] > 0) {
				minPathLen = pathLen[config];
			}
			endTime = System.currentTimeMillis();
			time[config] = endTime - startTime;
			avgTime[config] += time[config];
            bfs = null;

			for (int j = 0; j < trials; j++) {

				// Keyword Traversal, new rankings
				config = 0;
				KeywordTraverser.new_ranks = true;
				startTime = System.currentTimeMillis();
				KeywordTraverser keyNew = new KeywordTraverser(startPage, endPage);
				steps[config] = keyNew.traverse();
				avgSteps[config] += steps[config];
				pathLen[config] = keyNew.getPathLength();
				avgPathLen[config] += pathLen[config];
				if (minPathLen > pathLen[config] && pathLen[config] > 0) {
					minPathLen = pathLen[config];
				}
				endTime = System.currentTimeMillis();
				time[config] = endTime - startTime;
				avgTime[config] += time[config];
                keyNew = null;

				// Keyword Traversal, old rankings
				config = 1;
				KeywordTraverser.new_ranks = false;
				startTime = System.currentTimeMillis();
				KeywordTraverser keyOld = new KeywordTraverser(startPage, endPage);
				steps[config] = keyOld.traverse();
				avgSteps[config] += steps[config];
				pathLen[config] = keyOld.getPathLength();
				avgPathLen[config] += pathLen[config];
				if (minPathLen > pathLen[config] && pathLen[config] > 0) {
					minPathLen = pathLen[config];
				}
				endTime = System.currentTimeMillis();
				time[config] = endTime - startTime;
				avgTime[config] += time[config];
                keyOld = null;


				// Thread traversal, 0%, new rankings
				config = 2;
				MasterThread.new_ranks = true;
				MasterThread.view_threshold = 0;
				startTime = System.currentTimeMillis();
				MasterThread threadNew = new MasterThread(startPage, endPage);
				steps[config] = threadNew.traverse();
				avgSteps[config] += steps[config];
				pathLen[config] = threadNew.getPathLength();
				avgPathLen[config] += pathLen[config];
				if (minPathLen > pathLen[config] && pathLen[config] > 0) {
					minPathLen = pathLen[config];
				}
				endTime = System.currentTimeMillis();
				time[config] = endTime - startTime;
				avgTime[config] += time[config];
                threadNew = null;

				// Thread traversal, 0%, old rankings
				config = 3;
				MasterThread.new_ranks = false;
				MasterThread.view_threshold = 0;
				startTime = System.currentTimeMillis();
				MasterThread threadOld = new MasterThread(startPage, endPage);
				steps[config] = threadOld.traverse();
				avgSteps[config] += steps[config];
				pathLen[config] = threadOld.getPathLength();
				avgPathLen[config] += pathLen[config];
				if (minPathLen > pathLen[config] && pathLen[config] > 0) {
					minPathLen = pathLen[config];
				}
				endTime = System.currentTimeMillis();
				time[config] = endTime - startTime;
				avgTime[config] += time[config];
                threadOld = null;

				// Thread traversal, 25%, new rankings
				config = 4;
				MasterThread.new_ranks = true;
				MasterThread.view_threshold = .25;
				startTime = System.currentTimeMillis();
				MasterThread threadThresh = new MasterThread(startPage, endPage);
				steps[config] = threadThresh.traverse();
				avgSteps[config] += steps[config];
				pathLen[config] = threadThresh.getPathLength();
				avgPathLen[config] += pathLen[config];
				if (minPathLen > pathLen[config] && pathLen[config] > 0) {
					minPathLen = pathLen[config];
				}
				endTime = System.currentTimeMillis();
				time[config] = endTime - startTime;
				avgTime[config] += time[config];
                threadThresh = null;



				System.out.println("Trial " + j + "results: ");
				System.out.println("Config,\tpl,\tsteps,\ttime");
				for (int c = 0; c < CONFIGS; c++) {
					System.out.println(c + ",\t" + pathLen[c] + ",\t" + steps[c] + ",\t" + time[c]);
				}
			}
			int avgPathOverall = 0;
			for (int c = 0; c < CONFIGS-1; c++) {
				avgPathOverall += avgPathLen[c];
				avgPathLen[c] /= trials;
				avgSteps[c] /= trials;
				avgTime[c] /= trials;
			}
			avgPathOverall /= CONFIGS;

			System.out.println("Traverse " + i + "completed:");
			System.out.println("Min path: " + minPathLen + " Avg path: " + avgPathOverall);
			System.out.println("Averages:");
			System.out.println("Config,\tpl,\tsteps,\ttime");
			for (int c = 0; c < CONFIGS; c++) {
				System.out.println(c + ",\t" + avgPathLen[c] + ",\t" + avgSteps[c] + ",\t" + avgTime[c]);
			}

			CacheLinkProcessor.printMetrics();
		}





	}

}
